Title Banner

Previous Book Contents Book Index Next

Inside Macintosh: QuickDraw GX Printing /
Chapter 3 - Page Formatting and Dialog Box Customization / Using Format Objects and Collection Items to Format Pages


Associating Format Objects With Document Pages

Your application is responsible for managing the correspondence between format objects and individual pages in a document. For example, a user may create a document that consists of three pages. Through the Custom Page Setup dialog box, you can allow a user to specify that pages 1 and 2 use portrait orientation and page 3 uses landscape orientation. In this example, you need to store information that pages 1 and 2 use the default format, while page 3 uses a unique format object.

When a user saves a document containing multiple format objects, you need to save format collection information and then flatten the document's job object. In addition, when a user opens a document containing multiple format objects, you need to unflatten its corresponding job object and retrieve the format collection information. Flattening and unflattening a document's corresponding job object is discussed in the chapter "Core Printing Features" in this book.

There are several methods you can use to store formatting information. A common method, shown in this section, is to save the correspondence between format objects and pages in the format collection. Listing 3-19 shows a function that performs this task.

Listing 3-19 Saving the correspondence between format objects and document pages in a format collection

OSErr MySaveFormatRefs(MyDocumentPtr myDocument)
{
   OSErr       err = noErr;
   Handle      theFormatIdxList;
   Collection  fmtCollection;
   gxFormat    defaultFmt;

/* Create a handle containing all of the format object indices. */
   if (myDocument->numPages > 0)
   {

   /* 
      Obtain the format collection. If you have already have a
      document page-to-format object correspondence item stored, 
      remove it. 
   */
      defaultFmt = GXGetJobFormat(myDocument->documentJob, 1);
      fmtCollection = GXGetFormatCollection(defaultFmt);

      if (fmtCollection != nil)
         RemoveCollectionItem(fmtCollection, kMyFormatInfoType,
                               printingTagID);

      /* 
         Create a list of document page-to-format object 
         correspondences for the current document. If there are no 
         errors, add the item to the format collection for later 
         retrieval. 
      */
      err = MyCreateFormatIndexList(myDocument, 
                                             &theFormatIdxList);

      if (err == noErr)
      {
         HLock(theFormatIdxList);
         err = AddCollectionItem(fmtCollection, kMyFormatInfoType,
                                 printingTagID,
                                 GetHandleSize(theFormatIdxList),
                                 *theFormatIdxList);
         DisposHandle(theFormatIdxList);
      }
   }
   return err;
}
The MyCreateFormatIndexList function stores the index of each page's format object in a handle. The index of the format object for page 1 goes in the first long word of theFormatIdxList handle. The index of the next page's format object goes in the next long word, and so on. The handle is created and returned to the caller. Listing 3-20 shows the MyCreateFormatIndexList function.

Listing 3-20 Filling the handle

OSErr MyCreateFormatIndexList(MyDocumentPtr myDocument, Handle 
                              *theFormatIdxList)
{
   OSErr       err;
   long        fmtIdx, pg, *idxList;
   gxFormat    curFormat;

/* 
   Create a handle large enough to hold all of our entries. This 
   example uses NewHandleClear so that all of our indices are 
   initialized to 0 (an invalid format index). This application 
   stores a nil format reference for each page which uses the 
   default format. This allows us to indicate these "nil 
   references" by an index of 0 in our resource.
*/
   *theFormatIdxList = NewHandleClear(sizeof(long) * 
                                          (myDocument->numPages));
   err = MemError();


/* 
   If there aren't any errors, go through each format object. If 
   the format object is used by any pages of the document, store 
   the format object's index in those page entries of 
   theFormatIdxList. Skip format object #1, because that's the 
   default format. 
*/
   if (err == noErr)
   {
      HLock(*theFormatIdxList);
      idxList = (long *) **theFormatIdxList;
      
      for (fmtIdx = 2; fmtIdx <=
            GXCountJobFormats(myDocument->documentJob); fmtIdx++)
      {
         curFormat = GXGetJobFormat(myDocument->documentJob, 
                                    fmtIdx);

         for (pg = 1; pg <= myDocument->numPages; pg++)
            if (myDocument->pageFormat[pg -1] == curFormat)
               idxList[pg -1] = fmtIdx;
      }
      HUnlock(*theFormatIdxList);
   }
   return err;
}
Listing 3-21 shows how to retrieve format object correspondence from a format collection when a user opens a document containing multiple format objects. This function associates new format object references with a document, based upon the format object indices that are saved with the document. The function is called when a document is opened. The format object references are stored in the passed MyDocumentRec structure.

Listing 3-21 Retrieving the correspondence between document pages and format objects from a format collection

OSErr MyAdjustFormats(MyDocumentPtr myDocument)
{
   OSErr       err = noErr;
   Handle      theFormatIdxList = nil;
   gxFormat    theFormat, defaultFmt;
   long        pg, numPages, fmtIdx, *idxList, idx, listSize, 
               attribs;
   Collection  fmtCollection;

   /* 
      Get the format collection, and search for one of the
      document page-to-format object correspondence items. 
   */
   defaultFmt = GXGetJobFormat(myDocument->documentJob, 1);
   fmtCollection = GXGetFormatCollection(defaultFmt);
   
   /* 
      Load the item containing the correspondences. First,
      determine if the item exists. Next, create a handle to
      hold the item, and retrieve it. Because there is one
      long-word entry for each page of the document, determine
      the number of pages in the document. 
   */
   err = GetCollectionItemInfo(fmtCollection, kMyFormatInfoType,
                     gxPrintingTagID, &idx, &listSize, &attribs);
   if (err == noErr)
      theFormatIdxList = NewHandle(listSize);
   if (theFormatIdxList != nil)
   {
      HLock(theFormatIdxList);
      err = GetCollectionItem(fmtCollection, kMyFormatInfoType,
                        gxPrintingTagID, nil, *theFormatIdxList);
      numPages = listSize / sizeof(long);

      /* 
         Loop through each saved index. In this example, the first 
         index is for page 1, the second is for page 2, and so on.
         Call the GXGetJobFormat function for each saved
         index. Store the format references as they are
         processed. When finished, throw away the handle. 
      */
      idxList = (long *) *theFormatIdxList;
      for (pg = 1; pg <= numPages; pg++)
      {
         fmtIdx = idxList[pg -1];
         if (fmtIdx != nil)
            theFormat = GXGetJobFormat(myDocument->documentJob, 
                                                         fmtIdx);
         else
            theFormat = nil;
         myDocument->pageFormat[pg -1] = theFormat;
      }
      DisposHandle(theFormatIdxList);
   }
   return err;
}

Previous Book Contents Book Index Next

© Apple Computer, Inc.
7 JUL 1996




Navigation graphic, see text links

Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help